﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq ;
using System.Text ;
using System.Web;

namespace SugarFineUI.Framework.Uitility
{
    /// <summary>
    /// UploadFileCommand 的摘要说明
    /// 文件上传，图片上传                    
    /// </summary>
    public class UploadFileCommand : System.IDisposable //强制销毁上传文件流
    {
        public UploadFileCommand()
        {
        }

        public UploadFileCommand(HttpPostedFile upload)
        {
            fileUpload = new HttpPostedFileWrapper(upload) as HttpPostedFileBase;
        }
        public UploadFileCommand(HttpPostedFileBase upload)
        {
            fileUpload = upload;
        }

        private HttpPostedFileBase fileUpload;

        private long _size = 1 * 1024 * 1024; //默认1MB大小
        private string _error = string.Empty; //上传文件错误信息  
        private string _path = "Download"; //默认存放根目录下的路径地址
        private string _MIME = "rar|txt|doc|docx|ppt|pdf"; //文件类型
        private string _fileNameUrl = string.Empty; //文件名称+路径1
        private bool _isVerify = true; //是否验证上传文件

        //---图片---
        private int _limitwidth = 4000; //最大长度
        private int _limitheight = 3000; //最大宽度
        private bool _israte = true; //是否成比例
        private bool _isGifCompression = false; //是否启用gif图片压缩,压缩的

        private int _twidth = 0; //压缩图宽度
        private int _theight = 0; //压缩图高度

        private System.Drawing.Image _oImage; //图片缓存
       
        #region 上传文件

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <returns></returns>
        public bool UpLoadFile()
        {
            if (fileUpload == null)
            {
                _error = "请选择上传文件";
                return false;
            }

            if (_isVerify && !VerifyFile())
            {
                return false;
            }

            try
            {
                fileUpload.SaveAs(GetSaveFilePath()); //保存文件
            }
            catch (Exception ex)
            {
                Error += ex.Message;
            }

            return Error.Length == 0; //文件上传成功!

        }

        #endregion

        #region 图片上传

        /// <summary>
        /// 图片上传(默认:"等比压缩,动态gif,限定上传尺寸4000*3000,限定上传大小1MB,存放在根目录Download中")
        /// 图片上传完毕，要执行DisposeOImage()方法。
        /// </summary>
        /// <returns>返回是否成功保存图片</returns>
        public bool UpLoadIMG()
        {
            //验证图片
            if (_isVerify)
            {
                //oImage!=null为第2次上传图片，第一上传成功第二次也应该没问题,所以oImage == null需要再验证一次
                if (oImage == null)
                {
                    if (!VerifyImg())
                    {
                        return false;
                    }
                }
            }
            else //不验证文件
            {
                getOImage();
                if (Error.Length > 0) return false;
            }

            bool b = ThumbIMG(oImage);

            return b;
        }

        /// <summary>
        /// 获取图片对象
        /// </summary>
        private void getOImage()
        {
            //注意此方法，会导致 VerifyFile() 的  验证失败，转成流，fileUpload.ContentLength 就永远等于0。
            if (oImage == null)
            {
                try
                {
                    Stream oStream = fileUpload.InputStream;  //不能在此销毁Stream，不然生成缩略图报异常。
                    if (oImage == null)
                    {
                        oImage = Image.FromStream(oStream, true, false);
                    }
                }
                catch (Exception e)
                {
                    Error = "图片转换异常！";
                }
            }
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="image">图片文件</param>
        /// <returns></returns>
        public bool ThumbIMG(System.Drawing.Image image)
        {
            string savePath = GetSaveFilePath();

            int owidth = image.Width; //原图宽度 
            int oheight = image.Height; //原图高度

            if (_twidth == 0 && _theight > 0 && oheight > _theight)//压缩最大高度(算宽度)
            {
                if (_israte)//等比例缩放图片 
                {
                    _twidth = //等比设定宽度
                        (int)Math.Floor(Convert.ToDouble(owidth) * (Convert.ToDouble(_theight) / Convert.ToDouble(oheight)));
                }
                else//不等比
                {
                    _twidth = owidth;
                }
            }
            else if (_twidth > 0 && _theight == 0 && owidth > _twidth)//压缩最大宽度(算高度)
            {
                if (_israte)//等比例缩放图片 
                {
                    _theight = //等比设定高度
                        (int)Math.Floor(Convert.ToDouble(oheight) * (Convert.ToDouble(_twidth) / Convert.ToDouble(owidth)));
                }
                else//不等比
                {
                    _theight = oheight;
                }
            }
            else if (_twidth > 0 && _theight > 0) //按最大的宽和高
            {
                //等比例缩放图片 
                if (_israte)
                {
                    if (owidth >= oheight)
                    {
                        _theight = //等比设定高度
                            (int)Math.Floor(Convert.ToDouble(oheight) * (Convert.ToDouble(_twidth) / Convert.ToDouble(owidth)));
                    }
                    else
                    {
                        _twidth = //等比设定宽度
                            (int)Math.Floor(Convert.ToDouble(owidth) * (Convert.ToDouble(_theight) / Convert.ToDouble(oheight)));
                    }
                }
            }
            else //图片符合缩略图条件(宽高符合或没有要求)，直接上传
            {
                image.Save(savePath, ImageFormat.Jpeg);
                if (!image.Equals(oImage))
                    image.Dispose();

                //验证图片是否为真实的图片
                if (!IsAllowedUploadedImage(savePath))
                {
                    Error = "图片异常";
                    return false;
                }
                if (!CheckTrueImage(savePath))
                {
                    DeleteFile();
                    Error = "图片格式异常";
                    return false;
                }

                Error = string.Empty;
                return true;
            }

            //压缩宽度和高度 
            Image tImage = new Bitmap(_twidth, _theight);
            Graphics g = Graphics.FromImage(tImage);

            //开始保存图片至服务器
            try
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //设置高质量插值法 
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //设置高质量,低速度呈现平滑程度 
                g.Clear(Color.Transparent); //清空画布并以透明背景色填充 
                g.DrawImage(image, new Rectangle(0, 0, _twidth, _theight), new Rectangle(0, 0, owidth, oheight),
                    GraphicsUnit.Pixel);

                switch (GetFileExtension(savePath))
                {
                    case "gif":
                        if (_isGifCompression) //启用gif压缩，为动画
                        {
                            SetGifImage(image, savePath, _twidth, _theight);
                        }
                        else //把gif变成静态图片
                        {
                            tImage.Save(savePath, ImageFormat.Gif);
                        }
                        break;
                    case "bmp": tImage.Save(savePath, ImageFormat.Bmp); break;
                    case "emf": tImage.Save(savePath, ImageFormat.Emf); break;
                    case "exif": tImage.Save(savePath, ImageFormat.Exif); break;
                    case "icon": tImage.Save(savePath, ImageFormat.Icon); break;
                    case "memorybmp": tImage.Save(savePath, ImageFormat.MemoryBmp); break;
                    case "tiff": tImage.Save(savePath, ImageFormat.Tiff); break;
                    case "wmf": tImage.Save(savePath, ImageFormat.Wmf); break;
                    case "png": tImage.Save(savePath, ImageFormat.Png); break;
                    default: //jpeg jpg以及其他格式
                        tImage.Save(savePath, ImageFormat.Jpeg);
                        break;
                }

                //验证图片是否为真实的图片
                if (!IsAllowedUploadedImage(savePath))
                {
                    Error = "图片异常";
                    return false;
                }
                if (!CheckTrueImage(savePath))
                {
                    DeleteFile();
                    Error = "图片格式异常";
                    return false;
                }

                _error = string.Empty;
                return true;
            }
            catch (Exception ex)
            {
                _error = ex.Message;
                return false;
            }
            finally
            {
                g.Dispose();
                //释放资源 
                //oImage.Dispose();
                tImage.Dispose();
            }
        }

        /// <summary>
        /// 保存图片到指定的位置
        /// </summary>
        /// <param name="tImage"></param>
        /// <param name="path">/img/123.jgp格式</param>
        public static void SaveImage(Image tImage, string path)
        {
            CreatFolder(path);

            try
            {
                string savePath = HttpContext.Current.Server.MapPath("~" + path);

                //byte[] imgBytes = GetBytes(tImage);
                //System.IO.File.WriteAllBytes(path, imgBytes);

                switch (GetFileExtension(savePath))
                {
                    case "gif": tImage.Save(savePath, ImageFormat.Gif); break;
                    case "bmp": tImage.Save(savePath, ImageFormat.Bmp); break;
                    case "emf": tImage.Save(savePath, ImageFormat.Emf); break;
                    case "exif": tImage.Save(savePath, ImageFormat.Exif); break;
                    case "icon": tImage.Save(savePath, ImageFormat.Icon); break;
                    case "memorybmp": tImage.Save(savePath, ImageFormat.MemoryBmp); break;
                    case "tiff": tImage.Save(savePath, ImageFormat.Tiff); break;
                    case "wmf": tImage.Save(savePath, ImageFormat.Wmf); break;
                    case "png": tImage.Save(savePath, ImageFormat.Png); break;
                    default: //jpeg jpg以及其他格式
                        tImage.Save(savePath, ImageFormat.Jpeg);
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }

        private static byte[] GetBytes(Image image)
        {
            try
            {
                if (image == null) return null;
                using (Bitmap bitmap = new Bitmap(image))
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        bitmap.Save(stream, ImageFormat.Jpeg);
                        return stream.GetBuffer();
                    }
                }
            }
            finally
            {
                if (image != null)
                {
                    image.Dispose();
                    image = null;
                }
            }
        }

        /// <summary>
        /// 居中缩放图像
        /// </summary>
        /// <param name="oldImage">源</param>
        /// <param name="dest">目标</param>
        /// <param name="savePath">目标图片保存位置</param>
        public static void ImageScale(Bitmap oldImage, Bitmap dest, string savePath)
        {//https://blog.csdn.net/wwh1004/article/details/78635564
            if (oldImage == null || dest == null)
                throw new ArgumentNullException();

            Bitmap src = new Bitmap(oldImage);//将图片流复制到新的图片流中
            oldImage.Dispose(); //将原来的图片流释放，将图片文件进行解锁。

            double srcScale;
            double destScale;

            srcScale = (double)src.Width / src.Height;
            destScale = (double)dest.Width / dest.Height;

            Graphics g = Graphics.FromImage(dest);
            //计算长宽比
            try
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //设置高质量插值法 
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //设置高质量,低速度呈现平滑程度 
                if (srcScale - destScale >= 0 && srcScale - destScale <= 0.001)
                {
                    //长宽比相同
                    g.DrawImage(src, new Rectangle(0, 0, dest.Width, dest.Height),new Rectangle(0, 0, src.Width, src.Height), GraphicsUnit.Pixel);
                }
                else if (srcScale < destScale)
                {
                    //源长宽比小于目标长宽比，源的高度大于目标的高度
                    double newHeight;

                    newHeight = (double)dest.Height * src.Width / dest.Width;
                    g.DrawImage(src, new Rectangle(0, 0, dest.Width, dest.Height),
                        new Rectangle(0, (int)((src.Height - newHeight) / 2), src.Width, (int)newHeight),
                        GraphicsUnit.Pixel);
                }
                else
                {
                    //源长宽比大于目标长宽比，源的宽度大于目标的宽度
                    double newWidth;

                    newWidth = (double)dest.Width * src.Height / dest.Height;
                    g.DrawImage(src, new Rectangle(0, 0, dest.Width, dest.Height),
                        new Rectangle((int)((src.Width - newWidth) / 2), 0, (int)newWidth, src.Height),GraphicsUnit.Pixel);
                }

                SaveImage(dest, savePath);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
            finally
            {
                src.Dispose();
                g.Dispose();
            }
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="oldImgUrl">图片相对路径(例如： '/img/123.jpg')</param>
        /// <returns></returns>
        public bool ThumbIMG(string oldImgUrl)
        {
            System.Drawing.Image img = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(oldImgUrl));
            return ThumbIMG(img);
        }

        /// <summary>
        /// 所有图片创建完成后， 销毁图片缓存对象
        /// （由于2次以上 插入图片时，创建image会有异常（System.ArgumentException: 参数无效。），原因不清楚。故保留第一次image对象，来实现多图片创建！）
        /// </summary>
        public void DisposeOImage()
        {
            if (oImage != null) oImage.Dispose();
        }
        #endregion

        #region 公用方法

        /// <summary>
        /// 获取文件后缀名(例如:txt形式,)
        /// </summary>
        /// <param name="fileName">文件完整名称</param>
        /// <returns></returns>
        public static string GetFileExtension(string fileName)
        {
            return System.IO.Path.GetExtension(fileName)?.Substring(1).ToLower();
        }

        /// <summary>
        /// 获取文件名和扩展名
        /// </summary>
        /// <param name="fileName">文件完整名称</param>
        /// <returns></returns>
        public static string GetFileName(string fileName)
        {
            return System.IO.Path.GetFileName(fileName); //获取文件名和扩展名
        }


        /// <summary>
        /// 获取上传文件的MD5值,需要设置FileName_url值
        /// </summary>
        /// <returns></returns>
        public string GetFileMD5Code()
        {
            if (string.IsNullOrEmpty(_fileNameUrl))
            {
                return string.Empty;
            }

            return GetFileMD5Code(HttpContext.Current.Server.MapPath("~" + _fileNameUrl));
        }

        /// <summary>
        /// 得到文件的MD5值
        /// </summary>
        /// <param name="path">文件路径(使用方法HttpContext.Current.Server.MapPath)</param>
        /// <returns></returns>
        public static string GetFileMD5Code(string path)
        {
            try
            {
                if (System.IO.File.Exists(path))
                {
                    System.IO.FileStream Get_File = new System.IO.FileStream(path, System.IO.FileMode.Open,
                        System.IO.FileAccess.Read, System.IO.FileShare.Read);
                    System.Security.Cryptography.MD5CryptoServiceProvider Get_MD5 =
                        new System.Security.Cryptography.MD5CryptoServiceProvider();
                    byte[] Hash_byte = Get_MD5.ComputeHash(Get_File);
                    string Result = System.BitConverter.ToString(Hash_byte);
                    return Result.Replace("-", "");
                }
                else
                {
                    return string.Empty; //找不到文件
                }
            }
            catch (Exception e)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 验证文件是否符合标准(文件类型，大小)
        /// </summary>
        /// <returns></returns>
        public bool VerifyFile()
        {
            if (fileUpload == null)
            {
                _error = "请选择上传文件";
                return false;
            }

            string fileLastname = GetFileExtension(fileUpload.FileName);

            string[] strSTemp = _MIME.Split('|');
            bool isType = false;
            if (_MIME != "*")
            {
                for (int i = 0; i < strSTemp.Length; i++)
                {
                    if (strSTemp[i].Equals(fileLastname, StringComparison.InvariantCultureIgnoreCase))
                    {
                        isType = true;
                        break;
                    }
                }
            }
            else
            {
                isType = true;
            }

            if (!isType) //检查上传文件的格式是否有效
            {
                _error = "不受支持的类型,请重新选择!";
                return false;
            }

            if (fileUpload.ContentLength == 0 || fileUpload.ContentLength >= MaxSize) //检查文件的大小
            {
                _error = "指定的文件大小不符合要求!";
                return false;
            }

            return true;
        }

        /// <summary>
        /// 验证图片大小，文件类型
        /// </summary>
        /// <param name="oImage"></param>
        /// <returns></returns>
        private bool VerifyImg()
        {
            //设置图片格式默认值
            if (_MIME == "rar|txt|doc|docx|ppt|pdf")
            {
                _MIME = "jpg|jpeg|gif|png|bmp";
            }

            if (!VerifyFile()) //文件不符合要求
            {
                return false;
            }
            else
            {
                getOImage();
                if (Error.Length > 0) return false;

                int owidth = oImage.Width; //原图宽度 
                int oheight = oImage.Height; //原图高度
                //验证图片
                if (owidth > _limitwidth || oheight > _limitheight)
                {
                    _error = "超过允许的图片尺寸范围!";
                    return false;
                } //检查是否超出规定尺寸
            }

            return true;
        }

        /// <summary>
        /// 设置FileName_url值 ，才可删除文件或删除对应的图片
        /// </summary>
        public void DeleteFile()
        {
            try { File.Delete(System.Web.HttpContext.Current.Server.MapPath("~" + FileName_url)); } catch { }
        }

        /// <summary>
        /// 删除文件或删除对应的图片
        /// </summary>
        /// <param name="fileNameurl">文件路径(格式:~/123/123.txt)</param>
        public static void DeleteFile(string fileNameurl)
        {
            try { File.Delete(System.Web.HttpContext.Current.Server.MapPath(fileNameurl)); } catch { }
        }

        #endregion

        #region 图片和二进制流相互转换

        /// <summary>
        /// 二进制流转图片
        /// </summary>
        /// <param name="streamByte">二进制流</param>
        /// <returns>图片</returns>
        public static System.Drawing.Image GetImageByByte(byte[] streamByte)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream(streamByte);
            System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
            return img;
        }


        /// <summary>
        /// 图片转二进制
        /// </summary>
        /// <param name="imagepath">图片物理地址</param>
        /// <returns>二进制</returns>
        public static byte[] GetDyteByImage(string imagepath)
        {
            //根据图片文件的路径使用文件流打开，并保存为byte[]
            FileStream fs = new FileStream(imagepath, FileMode.Open); //可以是其他重载方法
            byte[] byData = new byte[fs.Length];
            fs.Read(byData, 0, byData.Length);
            fs.Close();
            return byData;
        }

        /// <summary>
        /// 图片转二进制
        /// </summary>
        /// <param name="imgPhoto">图片对象</param>
        /// <returns>二进制</returns>
        public static byte[] GetByteByImage(System.Drawing.Image imgPhoto)
        {
            //将Image转换成流数据，并保存为byte[]
            MemoryStream mstream = new MemoryStream();
            imgPhoto.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] byData = new Byte[mstream.Length];
            mstream.Position = 0;
            mstream.Read(byData, 0, byData.Length);
            mstream.Close();
            return byData;
        }

        #endregion

        #region 文件验证

        #region 检测上传真实类型与后缀名是否匹配,是否在允许列表中

        /// <summary>
        /// 检测上传图片是否真实，如果有异常删除图片，正常返回true
        /// </summary>
        /// <param name="path">图片物理路径</param>
        /// <returns></returns>
        public static bool IsAllowedUploadedImage(string path)
        {//https://bbs.csdn.net/topics/110179862
            //最后一部高级验证，图片上传后的操作，判断是否真的是图片
            StreamReader sr = new StreamReader(path, Encoding.Default);
            string strContent = sr.ReadToEnd();
            sr.Close();
            string str = "request|script|.getfolder|.createfolder|.deletefolder|.createdirectory|.deletedirectory|.saveas|wscript.shell|script.encode|server.|.createobject|execute|activexobject|language=";
            foreach (string s in str.Split('|'))
            {
                if (strContent.IndexOf(s,StringComparison.OrdinalIgnoreCase) != -1)
                {
                    try { File.Delete(path); } catch { }//删除
                    return false;
                }
            }
            return true;
        }


        /// <summary>
        /// 验证图片格式
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        public static bool CheckTrueImage(Image img)
        {
            MemoryStream ms = new MemoryStream();
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            return CheckTrueImage(ms);
        }

        /// <summary>
        /// 验证图片是否真实的格式
        /// </summary>
        /// <param name="path">图片物理路径</param>
        /// <returns></returns>
        public static bool CheckTrueImage(string path)
        {
            System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            return CheckTrueImage(fs);
        }

        /// <summary>
        /// 验证图片格式
        /// </summary>
        /// <param name="ms">图片的流</param>
        /// <returns></returns>
        public static bool CheckTrueImage(Stream ms)
        {
            try
            {
                System.IO.BinaryReader r = new System.IO.BinaryReader(ms);
                string fileCode = " ";
                int buffer;

                buffer = r.ReadByte();
                fileCode = buffer.ToString();
                buffer = r.ReadByte();
                fileCode += buffer.ToString();

                switch (fileCode)
                {
                    case "7173"://gif
                        return true;
                    case "255216"://jpg
                        return true;
                    case "13780"://png
                        return true;
                    case "6677"://bmp
                        return true;
                }
                return false;
            }
            catch (Exception exc)
            {
                return false;
            }
        }

        public enum FileExtension
        {
            /*文件扩展名说明.不一定准确 ，请实际测试下。来自网上
            *7173        gif 
            *255216      jpg
            *13780       png
            *6677        bmp
            *239187      txt,aspx,asp,sql
            *208207      xls.doc.ppt
            *6063        xml
            *6033        htm,html
            *4742        js
            *8075        xlsx,zip,pptx,mmap,zip
            *8297        rar   
            *01          accdb,mdb
            *7790        exe,dll           
            *5666        psd 
            *255254      rdp 
            *10056       bt种子 
            *64101       bat 
           */

            JPG = 255216,
            GIF = 7173,
            BMP = 6677,
            PNG = 13780,
            COM = 7790,
            EXE = 7790,
            DLL = 7790,
            RAR = 8297,
            ZIP = 8075,
            XML = 6063,
            HTML = 6033,
            ASPX = 239187,
            CS = 117115,
            JS = 119105,
            TXT = 210187,
            SQL = 255254,
            BAT = 64101,
            BTSEED = 10056,
            RDP = 255254,
            PSD = 5666,
            PDF = 3780,
            CHM = 7384,
            LOG = 70105,
            REG = 8269,
            HLP = 6395,
            DOC = 208207,
            XLS = 208207,
            DOCX = 208207,
            XLSX = 208207,
        }
        #endregion

        #region base64图片相互转换

        private static char[] base64CodeArray = new char[]
        {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4',  '5', '6', '7', '8', '9', '+', '/', '='
        };

        /// <summary>
        /// 是否base64字符串
        /// </summary>
        /// <param name="base64Str">要判断的字符串</param>
        /// <returns></returns>
        public static bool IsBase64(string base64Str)
        {
            byte[] bytes = null;
            return IsBase64(base64Str, out bytes);
        }

        /// <summary>
        /// 是否base64字符串
        /// </summary>
        /// <param name="base64Str">要判断的字符串</param>
        /// <param name="bytes">字符串转换成的字节数组</param>
        /// <returns></returns>
        public static bool IsBase64(string base64Str, out byte[] bytes)
        {
            //string strRegex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
            bytes = null;
            if (string.IsNullOrEmpty(base64Str))
                return false;
            else
            {
                if (base64Str.Contains(","))
                    base64Str = base64Str.Split(',')[1];
                if (base64Str.Length % 4 != 0)
                    return false;
                if (base64Str.Any(c => !base64CodeArray.Contains(c)))
                    return false;
            }
            try
            {
                bytes = Convert.FromBase64String(base64Str);
                return true;
            }
            catch (FormatException)
            {
                return false;
            }
        }

        /// <summary>
        /// base64编码转图片
        /// </summary>
        /// <param name="base64Code">base64编码</param>
        /// <returns>图片</returns>
        public static System.Drawing.Bitmap GetImageByBase64(string base64Code)
        {
            Bitmap bitmap = null;
            byte[] bytes = null;
            try
            {
                if (IsBase64(base64Code, out bytes))
                {
                    using (MemoryStream stream = new MemoryStream(bytes))
                    {
                        stream.Seek(0, SeekOrigin.Begin);//为了避免有时候流指针定位错误，显式定义一下指针位置
                        bitmap = new Bitmap(stream);
                    }
                }
            }
            catch (Exception)
            {
                bitmap = null;
            }
            return bitmap;
        }

        /// <summary>
        /// 将图片数据转换为Base64编码
        /// </summary>
        /// <param name="imagepath">图片物理地址</param>
        /// <returns>base64编码</returns>
        public static string GetBase64ByImage(string imagepath)
        {
            return Convert.ToBase64String(GetDyteByImage(imagepath));
        }

        /// <summary>
        /// 将图片数据转换为Base64编码
        /// </summary>
        /// <param name="imgPhoto">图片对象</param>
        /// <returns>base64编码</returns>
        public static string GetBase64ByImage(System.Drawing.Image imgPhoto)
        {
            return Convert.ToBase64String(GetByteByImage(imgPhoto));
        }

        /// <summary>
        /// 在网页上显示base64图片值。(例: <img src='值' >)
        /// </summary>
        /// <param name="base64Code"></param>
        /// <returns></returns>
        public static string ShowHtmlByBase64(string base64Code)
        {
            return string.Format("data:image/jpg;base64,{0}", base64Code);
        }
        #endregion

        public void Dispose()
        {
            DisposeOImage();
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 获取上传地址物理路径（并创建指定路径的文件夹）
        /// </summary>
        /// <returns></returns>
        private string GetSaveFilePath()
        {
            if (_fileNameUrl.Length == 0) //使用默认路径上传
            {
                //    /DownLoad/年/月/随机名称.后缀名
                _fileNameUrl = string.Format("/{0}/{1}/{2}/{3}", Path, DateTime.Now.Year, DateTime.Now.Month,
                    GetNewFileName(GetFileExtension(fileUpload.FileName)));
            }

            CreatFolder(); //创建临时文件夹

            return HttpContext.Current.Server.MapPath("~" + _fileNameUrl);
        }

        /// <summary>
        /// 生成新的随机数文件名称
        /// </summary>
        /// <param name="fileExtension">文件后缀名</param>
        /// <returns></returns>
        private string GetNewFileName(string fileExtension)
        {
            return string.Format("{0:hhmmssffff_}{1}.{2}", DateTime.Now, new Random().Next(100000, 999999), fileExtension);
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <returns></returns>
        private void CreatFolder()
        {
            CreatFolder(_fileNameUrl);
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <returns></returns>
        public static void CreatFolder(string savePath)
        {
            if (savePath.Length == 0)
            {
                return;
            }

            string tempPath = savePath;

            if (savePath.Substring(0, 2) == "~/")
            {
                tempPath = savePath.Replace("~/", "/");
            }
            else if (savePath.Substring(0, 1) != "/")
            {
                tempPath = string.Format("/{0}", savePath);
            }

            tempPath = tempPath.Replace(GetFileName(tempPath), String.Empty); //获取路径

            string saveNewPath = HttpContext.Current.Server.MapPath("~" + tempPath);
            if (!Directory.Exists(saveNewPath))
            {
                Directory.CreateDirectory(saveNewPath); //在根目录下建立文件夹
            }
        }

        /// <summary>
        /// 压缩gif图片
        /// </summary>
        /// <param name="img">原图</param>
        /// <param name="gifPath">缩略图保存路径</param>
        /// <param name="gifWidth">缩略图宽度度</param>
        /// <param name="gifHeight">缩略图高度</param>
        private static void SetGifImage(System.Drawing.Image img, string gifPath, int gifWidth, int gifHeight)
        {
            ////原图路径
            //string imgPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\0.gif"; //桌面/
            //原图
            //System.Drawing.Image img = System.Drawing.Image.FromFile(imgPath);

            //新图第一帧
            System.Drawing.Image new_img = new Bitmap(gifWidth, gifHeight);
            //新图其他帧
            System.Drawing.Image new_imgs = new Bitmap(gifWidth, gifHeight);
            //新图第一帧GDI+绘图对象
            Graphics g_new_img = Graphics.FromImage(new_img);
            //新图其他帧GDI+绘图对象
            Graphics g_new_imgs = Graphics.FromImage(new_imgs);

            try
            {
                //配置新图第一帧GDI+绘图对象
                g_new_img.CompositingMode = CompositingMode.SourceCopy;
                g_new_img.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g_new_img.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g_new_img.SmoothingMode = SmoothingMode.HighQuality;
                g_new_img.Clear(Color.FromKnownColor(KnownColor.Transparent));
                //配置其他帧GDI+绘图对象
                g_new_imgs.CompositingMode = CompositingMode.SourceCopy;
                g_new_imgs.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g_new_imgs.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g_new_imgs.SmoothingMode = SmoothingMode.HighQuality;
                g_new_imgs.Clear(Color.FromKnownColor(KnownColor.Transparent));
                //遍历维数
                foreach (Guid gid in img.FrameDimensionsList)
                {
                    //因为是缩小GIF文件所以这里要设置为Time
                    //如果是TIFF这里要设置为PAGE
                    FrameDimension f = FrameDimension.Time;
                    //获取总帧数
                    int count = img.GetFrameCount(f);
                    //保存标示参数
                    System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.SaveFlag;
                    //
                    EncoderParameters ep = null;
                    //图片编码、解码器
                    ImageCodecInfo ici = null;
                    //图片编码、解码器集合
                    ImageCodecInfo[] icis = ImageCodecInfo.GetImageDecoders();
                    //为 图片编码、解码器 对象 赋值
                    foreach (ImageCodecInfo ic in icis)
                    {
                        if (ic.FormatID == ImageFormat.Gif.Guid)
                        {
                            ici = ic;
                            break;
                        }
                    }

                    //每一帧
                    for (int c = 0; c < count; c++)
                    {
                        //选择由维度和索引指定的帧
                        img.SelectActiveFrame(f, c);
                        //第一帧
                        if (c == 0)
                        {
                            //将原图第一帧画给新图第一帧
                            g_new_img.DrawImage(img, new Rectangle(0, 0, gifWidth, gifHeight),
                                new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
                            //把振频和透明背景调色板等设置复制给新图第一帧
                            for (int i = 0; i < img.PropertyItems.Length; i++)
                            {
                                new_img.SetPropertyItem(img.PropertyItems[i]);
                            }

                            ep = new EncoderParameters(1);
                            //第一帧需要设置为MultiFrame
                            ep.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);
                            //保存第一帧
                            new_img.Save(gifPath, ici, ep);
                        }
                        //其他帧
                        else
                        {
                            //把原图的其他帧画给新图的其他帧
                            g_new_imgs.DrawImage(img, new Rectangle(0, 0, gifWidth, gifHeight),
                                new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
                            //把振频和透明背景调色板等设置复制给新图第一帧
                            for (int i = 0; i < img.PropertyItems.Length; i++)
                            {
                                new_imgs.SetPropertyItem(img.PropertyItems[i]);
                            }

                            ep = new EncoderParameters(1);
                            //如果是GIF这里设置为FrameDimensionTime
                            //如果为TIFF则设置为FrameDimensionPage
                            ep.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionTime);
                            //向新图添加一帧
                            new_img.SaveAdd(new_imgs, ep);
                        }
                    }

                    ep = new EncoderParameters(1);
                    //关闭多帧文件流
                    ep.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
                    new_img.SaveAdd(ep);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //释放文件
                //img.Dispose();
                new_img.Dispose();
                new_imgs.Dispose();
                g_new_img.Dispose();
                g_new_imgs.Dispose();
            }
        }
        #endregion

        #region 属性
        /// <summary>
        /// 文件类型 默认"rar|txt|doc|docx|ppt|pdf", 全部文件设置为"*"。图片上传默认值为"jpg|jpeg|gif|png|bmp"
        /// </summary>
        public string MIME{get { return _MIME; }set { _MIME = value; }}

        /// <summary>
        ///上传文件错误信息
        /// </summary>
        public string Error{get { return _error; }set { _error = value; }}

        /// <summary>
        /// 设置文件大小 默认1*1024*1024字节（1MB）
        /// </summary>
        public long MaxSize{get { return _size; }set { _size = value; }}

        /// <summary>
        /// 默认存放根目录下的路径地址 Download
        /// </summary>
        public string Path{get { return _path; }set { _path = value; }}

        /// <summary>
        /// 上传文件名称+路径(可指定位置,例： /download/123.txt )
        /// </summary>
        public string FileName_url{get { return _fileNameUrl; }set { _fileNameUrl = value; }}

        /// <summary>
        /// 是否验证上传文件，默认true
        /// </summary>
        public bool IsVerify{get { return _isVerify; }set { _isVerify = value; }}

        #region 图片
        /// <summary>
        /// 限定宽度 默认4000
        /// </summary>
        public int Img_LimitWidth{get { return _limitwidth; }set { _limitwidth = value; }}

        /// <summary>
        /// 限定高度 默认3000
        /// </summary>
        public int Img_LimitHeight{get { return _limitheight; }set { _limitheight = value; }}

        /// <summary>
        /// 压缩图宽度 默认0
        /// </summary>
        public int Img_TWidth{get { return _twidth; }set { _twidth = value; }}

        /// <summary>
        /// 压缩图高度 默认0
        /// </summary>
        public int Img_THeight{get { return _theight; }set { _theight = value; }}

        /// <summary>
        /// 是否成比例（默认true）
        /// </summary>
        public bool Img_IsRate{get { return _israte; }set { _israte = value; }}

        /// <summary>
        /// 是否gif图片生成动态(gif图片压缩)。默认false
        /// </summary>
        public bool Img_IsGifCompression{get { return _isGifCompression; }set { _isGifCompression = value; }}
        #endregion

        /// <summary>
        /// 缓存图片对象(不暴露给外部)，
        /// 由于2次以上 插入图片时，创建image会有异常（System.ArgumentException: 参数无效。），原因不清楚。故保留第一次image对象，来实现多图片创建！
        /// </summary>
        public System.Drawing.Image oImage{get { return _oImage; }set { _oImage = value; }}

        #endregion
    }
}

#region 例子：多图片上传调用
/*
      protected void btn1_OnClick(object sender, EventArgs e)
        {
            using (UploadFileCommand ufc=new UploadFileCommand(this.upload1.PostedFile))
            {
                string errroInfo = string.Empty;

                string fileInfo = string.Empty;

                if (!ufc.UpLoadIMG())//上传原图
                {
                    errroInfo+=ufc.Error;
                }
                else
                {
                    fileInfo += ufc.FileName_url + "|";
                }


                // 生成缩略图1
                ufc.Img_THeight = 100;
                ufc.Img_TWidth = 100;
                ufc.FileName_url = string.Empty;//清空指定路径，并使用默认方式上传

                if (!ufc.UpLoadIMG())//上传缩略图
                {
                    errroInfo += ufc.Error;
                }
                else
                {
                    fileInfo += ufc.FileName_url + "|";
                }


                // 生成缩略图2。并上传指定位置
                string tempName = UploadFileCommand.GetFileName(ufc.FileName_url);//获取上一次上传的文件名

                ufc.Img_THeight = 200;//缩略图最高尺寸可选
                ufc.Img_TWidth = 300;//缩略图最宽尺寸可选
                ufc.FileName_url = "/img/" + tempName;//指定位置

                if (!ufc.UpLoadIMG())//上传缩略图
                {
                    errroInfo += ufc.Error;
                }
                else
                {
                    fileInfo += ufc.FileName_url + "|";
                }

                //显示消息
                if(errroInfo.Length>0)
                    Alert.Show(errroInfo );
                else
                    Alert.Show(fileInfo);
           
            }
        }
        
     
     */
#endregion

#region 例子：接收base64编码格式的图片并上传
/*
  var img = UploadFileCommand.GetImageByBase64(image_data);

            using (UploadFileCommand ufc = new UploadFileCommand())
            {
                ufc.oImage = img ;
                ufc.Img_THeight = 180 ;
                ufc.Img_TWidth = 180 ;
                ufc.FileName_url = "/attached/head/" + sm.MerchantID+".jpg" ;
                ufc.UpLoadIMG() ;
            }
 */
#endregion

#region 版本Log
//注意：GDI+ 中发生一般性错误。发送这个问题:
//1 主要是保存的路径,是否使用了HttpContext.Current.Server.MapPath转换！！？？
//2 Graphics 销毁了，image是没办法save的。

//版本号:20190416
// 更改GetImageByBase64方法返回Bitmap对象
// ImageScale方法改成高质量生成图片

//版本号:20190329
// 增加base64图片转换判断，解决转换失败的bug(不是正确的base64)
// 增加判断是否为真实图片

//版本号:20190326
// 增加图像居中缩放,增加保存image到指定的位置

//版本号:20190315
// 增加缩略图按照最高或最宽上传

//版本号:20190306
// 增加HttpPostedFileBase

//版本号:20180418
// 解决上传缩略图路径不正确的bug
// (2017-8-17) 增加图片 和 二进制 base64 转换方法
// (2017-8-3) 优化代码并可以指定上传位置
#endregion